package service

import (
	"context"

	pb "gitee.com/zhangxinzx/notebook/api/notebook/v1"
	"gitee.com/zhangxinzx/notebook/internal/biz"
	"github.com/go-kratos/kratos/v2/log"
	"go.opentelemetry.io/otel"
)

func NewNotebookService(notebook *biz.NotebookUsecase, logger log.Logger) *NotebookService {
	return &NotebookService{
		notebook: notebook,
		log:      log.NewHelper(logger),
	}
}

func (nbs *NotebookService) CreateNote(ctx context.Context, req *pb.CreateNoteRequest) (*pb.CreateNoteReply, error) {
	nbs.log.Infof("input data %v", req)
	note := &biz.Note{
		Title:   req.Title,
		Content: req.Content,
	}
	if req.Category != nil && req.Category.Id != 0 {
		note.CategoryID = req.Category.Id
	}
	err := nbs.notebook.CreateNote(ctx, note)

	return &pb.CreateNoteReply{}, err
}

func (nbs *NotebookService) GetNote(ctx context.Context, req *pb.GetNoteRequest) (*pb.GetNoteReply, error) {
	tr := otel.Tracer("api")
	ctx, span := tr.Start(ctx, "GetNote")
	defer span.End()

	n, err := nbs.notebook.GetNote(ctx, req.Id)
	if err != nil {
		return nil, err
	}

	return &pb.GetNoteReply{Note: &pb.Note{Id: n.ID, Title: n.Title, Content: n.Content, Category: &pb.Category{Id: n.CategoryID}}}, nil
}

func (nbs *NotebookService) UpdateNote(ctx context.Context, req *pb.UpdateNoteRequest) (*pb.UpdateNoteReply, error) {
	nbs.log.Infof("input data %v", req)
	err := nbs.notebook.UpdateNote(ctx, req.Id, &biz.Note{
		Title:   req.Title,
		Content: req.Content,
	})

	return &pb.UpdateNoteReply{}, err
}

func (nbs *NotebookService) DeleteNote(ctx context.Context, req *pb.DeleteNoteRequest) (*pb.DeleteNoteReply, error) {
	nbs.log.Infof("input data %v", req)
	err := nbs.notebook.DeleteNote(ctx, req.Id)

	return &pb.DeleteNoteReply{}, err
}

func (nbs *NotebookService) MoveNote(ctx context.Context, req *pb.MoveNoteRequest) (*pb.MoveNoteReply, error) {
	nbs.log.Infof("input data %v", req)
	err := nbs.notebook.MoveNote(ctx, req.Id, req.CategoryID)

	return &pb.MoveNoteReply{}, err
}

func (nbs *NotebookService) CreateCategory(ctx context.Context, req *pb.CreateCategoryRequest) (*pb.CreateCategoryReply, error) {
	nbs.log.Infof("input data %v", req)
	err := nbs.notebook.CreateCategory(ctx, &biz.Category{
		Name: req.Name,
	})

	return &pb.CreateCategoryReply{}, err
}

func (nbs *NotebookService) GetCategory(ctx context.Context, req *pb.GetCategoryRequest) (*pb.GetCategoryReply, error) {
	nbs.log.Infof("input data %v", req)
	notes, err := nbs.notebook.GetCategory(ctx, req.Id)
	if err != nil {
		return &pb.GetCategoryReply{}, err
	}
	reply := &pb.GetCategoryReply{}
	reply.Results = make([]*pb.Note, 0, len(notes))
	for _, note := range notes {
		reply.Results = append(reply.Results, &pb.Note{
			Id:    note.ID,
			Title: note.Title,
		})
	}

	return reply, nil
}

func (nbs *NotebookService) ListCategory(ctx context.Context, req *pb.ListCategoryRequest) (*pb.ListCategoryReply, error) {
	nbs.log.Infof("input data %v", req)
	categories, err := nbs.notebook.ListCategory(ctx)
	if err != nil {
		return &pb.ListCategoryReply{}, err
	}
	reply := &pb.ListCategoryReply{}
	reply.Results = make([]*pb.Category, 0, len(categories))
	for _, category := range categories {
		reply.Results = append(reply.Results, &pb.Category{
			Id:   category.ID,
			Name: category.Name,
		})
	}

	return reply, nil
}

func (nbs *NotebookService) UpdateCategory(ctx context.Context, req *pb.UpdateCategoryRequest) (*pb.UpdateCategoryReply, error) {
	nbs.log.Infof("input data %v", req)
	err := nbs.notebook.UpdateCategory(ctx, req.Id, &biz.Category{
		Name: req.Name,
	})

	return &pb.UpdateCategoryReply{}, err
}

func (nbs *NotebookService) DeleteCategory(ctx context.Context, req *pb.DeleteCategoryRequest) (*pb.DeleteCategoryReply, error) {
	nbs.log.Infof("input data %v", req)
	err := nbs.notebook.DeleteCategory(ctx, req.Id)

	return &pb.DeleteCategoryReply{}, err
}
